import { defineStore } from 'pinia';
import { useIdle } from '@vueuse/core';
import { useWebSocket } from '@vueuse/core';
import mitt from 'mitt';
import { uniqueSlash } from '~/utils/urlUtils';

export type WebSocketMessage = {
    data?: any;
    type?: 'ping' | 'close' | 'updatePermsAndMenus' | 'updateOnlineUserCount';
};

type Events = {
    onlineUser: number;
};

export const useWebSocketStore = defineStore('websocket', () => {
    const emitter = mitt<Events>();
    const userStore = useUserStore();
    const { idle } = useIdle(5 * 60 * 1000); // 5 min

    const serverConnected = ref(true);
    const onlineUserCount = ref(0);
    let websocket: ReturnType<typeof useWebSocket> | null = null;

    // 自动重连相关状态
    const reconnectAttempts = ref(0);
    const maxReconnectAttempts = 5;
    const reconnectInterval = 5000; // 5秒

    watch(serverConnected, (val) => {
        if (val && userStore.accessToken) {
            initWebSocket();
        } else {
            closeWebSocket();
        }
    });

    watch(idle, (idleValue) => {
        if (idleValue) {
            closeWebSocket();
        } else if (userStore.accessToken) {
            setServerConnectStatus(true);
        }
    });

    /** 初始化 WebSocket 连接 */
    const initWebSocket = async () => {
        if (websocket) {
            websocket.close();
        }

        const wsUrl = uniqueSlash(`${import.meta.env.VITE_WS_API_URL}/api/ws/?token=${userStore.accessToken}`).replace(/^http/, 'ws');

        websocket = useWebSocket(wsUrl, {
            autoReconnect: {
                retries: maxReconnectAttempts,
                delay: reconnectInterval,
            },
            heartbeat: {
                message: JSON.stringify({ type: 'ping' }),
                interval: 30000, // 30秒发送一次心跳
            },
            onConnected: (ws) => {
                console.log('WebSocket connected');
                reconnectAttempts.value = 0;
                serverConnected.value = true;
            },
            onDisconnected: (ws, event) => {
                console.log('WebSocket disconnected', event);
                serverConnected.value = false;
            },
            onError: (ws, event) => {
                console.error('WebSocket error', event);
            },
            onMessage: (ws, event) => {
                try {
                    const { type, data } = JSON.parse(event.data) as WebSocketMessage;
                    handleWebSocketMessage(type, data);
                } catch (err) {
                    console.error('Failed to parse WebSocket message', err);
                }
            },
        });
    };

    /** 处理 WebSocket 消息 */
    const handleWebSocketMessage = (type: string | undefined, data: any) => {
        // 服务器关闭 WebSocket 连接
        if (type === 'close') {
            closeWebSocket();
        }
        // 当用户的权限及菜单有变更时，重新获取权限及菜单
        else if (type === 'updatePermsAndMenus') {
            // 处理权限和菜单更新
        }
        // 在线用户数量变更时
        else if (type === 'updateOnlineUserCount') {
            onlineUserCount.value = ~~data;
            emitter.emit('onlineUser', onlineUserCount.value);
        }
    };

    /** 关闭 WebSocket 连接 */
    const closeWebSocket = () => {
        serverConnected.value = false;
        websocket?.close();
        websocket = null;
    };

    /** 设置服务端连接状态 */
    const setServerConnectStatus = (isConnect: boolean) => {
        serverConnected.value = isConnect;
    };

    /** 发送消息到服务器 */
    const sendMessage = (message: WebSocketMessage) => {
        if (websocket && websocket.status.value === 'OPEN') {
            websocket.send(JSON.stringify(message));
        } else {
            console.warn('WebSocket is not connected');
        }
    };

    return {
        emitter,
        serverConnected,
        onlineUserCount,
        initWebSocket,
        closeWebSocket,
        setServerConnectStatus,
        sendMessage,
    };
});
